package vip.specimen.system.common.handler;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.hibernate.exception.JDBCConnectionException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.transaction.CannotCreateTransactionException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import vip.specimen.system.common.enums.ResultCode;
import vip.specimen.system.result.JsonResult;

/**
 * *@Author: 余浪人
 * *@Date：2021/2/5 15:10
 * *@Email:yulangren520@Gmail.com
 * *@QQ:1368419640
 **/
@ControllerAdvice
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {
    /**
     * 处理空指针的异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = NullPointerException.class)
    public JsonResult<Object> exceptionHandler(NullPointerException e) {
        log.error("发生空指针异常！原因是:" + e.getMessage());
        e.printStackTrace();
        return JsonResult.error(ResultCode.ERROR_NULL_POINTER);
    }

    /**
     * 请求序列化失败
     *
     * @param e 异常
     * @return
     */
    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    public JsonResult<Object> exceptionHandler(HttpMessageNotReadableException e) {
        log.error(e.getMessage());
        return JsonResult.error(ResultCode.ERROR_HTTP_MESSAGE_NOT_READABLE);
    }

    /**
     * body数据验证异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public JsonResult<JSONObject> exceptionHandler(MethodArgumentNotValidException e) throws SystemExceptionHandler {
        FieldError fieldError = e.getBindingResult().getFieldError();
        log.error("数据验证失败[" + fieldError.getField() + "]: " + fieldError.getDefaultMessage());
        JSONObject json = new JSONObject();
        json.put("error", fieldError.getDefaultMessage());
        return JsonResult.error(ResultCode.DATA_VALIDATION_FAIL, json);
    }

    /**
     * 自定义错误
     *
     * @param e 对象
     * @return result
     */
    @ExceptionHandler(value = SystemExceptionHandler.class)
    public JsonResult exceptionHandler(SystemExceptionHandler e) {
        JSONObject json = new JSONObject();
        json.put("error", e.getMessage());
        return JsonResult.error((int) e.getStatus(), e.getMessage(), json);
    }

    /**
     * 数据完整性异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = DataIntegrityViolationException.class)
    public JsonResult exceptionHandler(DataIntegrityViolationException e) {
        JSONObject json = new JSONObject();
        json.put("error", ResultCode.DATA_UNREPEATABLE_CODE_INSERT.getMessage());
        return JsonResult.error(ResultCode.DATA_UNREPEATABLE_CODE_INSERT, json);
    }

    /**
     * 数据库连接失败
     *
     * @param e e
     * @return 响应
     */
    @ExceptionHandler(value = DataAccessResourceFailureException.class)
    public JsonResult exceptionHandler(DataAccessResourceFailureException e) {
        JSONObject json = new JSONObject();
        json.put("error", ResultCode.UNABLE_TO_ACQUIRE_JDBC_CONNECTION.getMessage());
        return JsonResult.error(ResultCode.UNABLE_TO_ACQUIRE_JDBC_CONNECTION, json);
    }

    /**
     * 未登录异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = UnauthenticatedException.class)
    public JsonResult exceptionHandler(UnauthenticatedException e) {
        JSONObject json = new JSONObject();
        json.put("error", ResultCode.ERROR_NOT_LOGIN.getMessage());
        return JsonResult.error(ResultCode.ERROR_NOT_LOGIN, json);
    }

    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public JsonResult<JSONObject> exceptionHandler(MissingServletRequestParameterException e) throws SystemExceptionHandler {
        log.error("缺少参数: " + e.getMessage());
        JSONObject json = new JSONObject();
        json.put("error", e.getMessage());
        return JsonResult.error(ResultCode.DATA_VALIDATION_FAIL, json);
    }

    /**
     * 未定义的请求 异常
     *
     * @param e 异常
     * @return msg
     */
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    public JsonResult<String> exceptionHandler(HttpRequestMethodNotSupportedException e) {
        return JsonResult.error(ResultCode.REQUEST_METHOD_NOT_SUPPORTED, "请求失败！原因是:" + e.getMessage());
    }

    /**
     * 请求头ContentType 错误
     *
     * @param e 异常
     * @return msg
     */
    @ExceptionHandler(value = HttpMediaTypeNotSupportedException.class)
    public JsonResult<String> exceptionHandler(HttpMediaTypeNotSupportedException e) {
        return JsonResult.error(ResultCode.ERROR_HTTP_MEDIA_TYPE_NOT_SUPPORTED, "请求错误！原因是:" + e.getMessage());
    }

    /**
     * 对象没有权限
     *
     * @param e e
     * @return
     */
    @ExceptionHandler(value = UnauthorizedException.class)
    public JsonResult<Object> exceptionHandler(UnauthorizedException e) {
        log.error("对象没有权限" + e.getMessage());
        return JsonResult.error(ResultCode.ERROR_NOT_PERMISSION);
    }

    @ExceptionHandler(value = JDBCConnectionException.class)
    public JsonResult<Object> exceptionHandler(JDBCConnectionException e) {
        log.error("无法获取JDBC连接");
        return JsonResult.error(ResultCode.UNABLE_TO_ACQUIRE_JDBC_CONNECTION);
    }

    @ExceptionHandler(value = InvalidDataAccessResourceUsageException.class)
    public JsonResult<Object> exceptionHandler(InvalidDataAccessResourceUsageException e) {
        log.error("无效的数据资源服务");
        return JsonResult.error(ResultCode.INVALID_DATA_ACCESS_RESOURCE_USAGE);
    }

    /**
     * 事务建立异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = CannotCreateTransactionException.class)
    public JsonResult<Object> exceptionHandler(CannotCreateTransactionException e) {
        log.error("建立事务失败");
        return JsonResult.error(ResultCode.CANNOT_CREATE_TRANSACTION);
    }

    /**
     * 其他异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public JsonResult<String> exceptionHandler(Exception e) {
        e.printStackTrace();
        log.error("发生致命异常！原因是:" + e.getMessage());
        return JsonResult.error(ResultCode.ERROR_SERVER, "发生异常！原因是:" + e.getMessage());
    }
}
